Crate mcdata

source ·
Expand description

§mcdata

A Rust library providing traits and types representing various Minecraft NBT structures.

§Overview

Currently, this crate provides three traits along with some implementations of those traits:

There’s one “generic” implementation for each of these in the corresponding module. Other implementations are locked behind features.

With serde support enabled, all types in this crate can be full serialized and deserialized from/to NBT. The recommended crate for that is fastnbt which is also internally used by the types in this crate. For example entity::GenericEntity is almost fully represented by a fastnbt::Value.

§A Warning for Block Entities

If you intend to use any version-specific BlockEntity type with litematica files, beware that there was a bug in litematica since version 1.18.0-0.9.0 that was only fixed in 1.20.1-0.15.3 which caused the block entity IDs to not be included in saved schematics. The block entity types do support deserialization without an ID, but that can never be perfect. For instance, barrels and chests in 1.18 have the same exact NBT structure, but barrels will always be tested first when deserializing, so chests will also be deserialized as barrels when there’s no ID distinguishing the two. During serialization, the ID will always be included, so such a chest would become a barrel by just reading and writing the NBT. If that’s a problem for you, consider using GenericBlockEntity instead which won’t mess with missing IDs.

§Examples

Block States
use mcdata::latest::{BlockState, props};

let banjo = BlockState::NoteBlock {
    instrument: props::NoteBlockInstrument::Banjo,
    note: bounded_integer::BoundedU8::new(10).unwrap(),
    powered: false,
};
let banjo_nbt = fastnbt::nbt!({
    "Name": "minecraft:note_block",
    "Properties": {
        "instrument": "banjo",
        "note": "10",
        "powered": "false",
    },
});
assert_eq!(fastnbt::to_value(&banjo), Ok(banjo_nbt));
Entities
use std::collections::HashMap;
use mcdata::latest::{Entity, entity_types as types, entity_compounds as compounds};

let axolotl = Entity::Axolotl(types::Axolotl {
    from_bucket: false,
    variant: 0,
    parent: types::Animal {
        in_love: 0,
        love_cause: None,
        parent: types::AgeableMob {
            age: 0,
            forced_age: 0,
            parent: types::PathfinderMob {
                parent: types::Mob {
                    armor_drop_chances: vec![0.085; 4],
                    armor_items: vec![HashMap::new(); 4],
                    can_pick_up_loot: false,
                    death_loot_table: None,
                    body_armor_drop_chance: None,
                    death_loot_table_seed: None,
                    hand_drop_chances: vec![0.085; 2],
                    hand_items: vec![HashMap::new(); 2],
                    left_handed: false,
                    no_ai: None,
                    persistence_required: false,
                    body_armor_item: None,
                    leash: None,
                    parent: types::LivingEntity {
                        absorption_amount: 0.,
                        attributes: vec![compounds::AttributeInstance_save {
                            base: 1.,
                            modifiers: None,
                            name: "minecraft:generic.movement_speed".into(),
                        }],
                        brain: Some(fastnbt::nbt!({ "memories": {} })),
                        death_time: 0,
                        fall_flying: false,
                        health: 14.,
                        hurt_by_timestamp: 0,
                        hurt_time: 0,
                        sleeping_x: None,
                        sleeping_y: None,
                        sleeping_z: None,
                        active_effects: None,
                        parent: types::Entity {
                            air: 6000,
                            custom_name: None,
                            custom_name_visible: None,
                            fall_distance: 0.,
                            fire: -1,
                            glowing: None,
                            has_visual_fire: None,
                            invulnerable: false,
                            motion: vec![0.; 3],
                            no_gravity: None,
                            on_ground: false,
                            passengers: None,
                            portal_cooldown: 0,
                            pos: vec![-0.5, 0., 1.5],
                            rotation: vec![-107.68715, 0.],
                            silent: None,
                            tags: None,
                            ticks_frozen: None,
                            uuid: 307716075036743941152627606223512221703,
                        },
                    },
                },
            },
        },
    },
});
let axolotl_nbt = fastnbt::nbt!({
    "id": "minecraft:axolotl",
    "FromBucket": false,
    "Variant": 0,
    "InLove": 0,
    "Age": 0,
    "ForcedAge": 0,
    "ArmorDropChances": vec![0.085_f32; 4],
    "ArmorItems": [{}, {}, {}, {}],
    "CanPickUpLoot": false,
    "HandDropChances": vec![0.085_f32; 2],
    "HandItems": [{}, {}],
    "LeftHanded": false,
    "PersistenceRequired": false,
    "AbsorptionAmount": 0_f32,
    "Attributes": [{
        "Base": 1.,
        "Name": "minecraft:generic.movement_speed",
    }],
    "Brain": { "memories": {} },
    "DeathTime": 0_i16,
    "FallFlying": false,
    "Health": 14_f32,
    "HurtByTimestamp": 0,
    "HurtTime": 0_i16,
    "Air": 6000_i16,
    "FallDistance": 0_f32,
    "Fire": -1_i16,
    "Invulnerable": false,
    "Motion": vec![0.; 3],
    "OnGround": false,
    "PortalCooldown": 0,
    "Pos": [-0.5, 0., 1.5],
    "Rotation": [-107.68715_f32, 0_f32],
    "UUID": [I; -411044392, 312166398, -1883713137, 1472542727],
});
assert_eq!(fastnbt::to_value(&axolotl), Ok(axolotl_nbt));
Block Entities
use mcdata::latest::{BlockEntity, block_entity_types as types};

let command_block = BlockEntity::CommandBlock(types::CommandBlockEntity {
    command: "/say hi".into(),
    custom_name: None,
    last_execution: None,
    last_output: None,
    success_count: 2,
    track_output: true,
    update_last_execution: true,
    auto: false,
    condition_met: false,
    powered: false,
    parent: types::BlockEntity {
        x: 0,
        y: 10,
        z: -5,
    },
});
let command_block_nbt = fastnbt::nbt!({
    "id": "minecraft:command_block",
    "Command": "/say hi",
    "SuccessCount": 2,
    "TrackOutput": true,
    "UpdateLastExecution": true,
    "auto": false,
    "conditionMet": false,
    "powered": false,
    "x": 0,
    "y": 10,
    "z": -5,
});
assert_eq!(fastnbt::to_value(&command_block), Ok(command_block_nbt));

§Where does this data come from?

As you can imagine, I did not enter all this data by hand. It is automatically extracted from the Minecraft jars using a combination of two custom tools:

  1. The “data-extractor” is a Java file that acts as a Fabric mod and gets some data at runtime using reflection. This includes everything about block states, and some things about entities (the IDs of all entities and their corresponding classes).
  2. The (badly named) “class-parser” is almost like a JVM written in Kotlin which takes the data about entities from the “data-extractor” and “interprets” the Minecraft jars to gather information about their NBT structure. This is necessary because entity NBT is unstructured and the only thing that defines the structure is the actual code itself. This is obviously still a brittle approach, but the best I could think of. Some things are also very difficult to properly support in this “JVM”, mainly Minecraft’s Codecs which are getting used more and more with new Minecraft updates. This together means that all types in this crate which describe NBT structure might not be fully correct. If you find any discrepancies, please open an issue ticket.

If you want to contribute to mcdata in any way that involves changing the generated code, you can run these tools along with the actual code generation using cargo xtask codegen. Just make sure you have a working Java 21 JDK, git, and deno installed and on your PATH.

§Features

  • serde — Provide implementations of serde’s Serialize and Deserialize traits for the various types
  • block-states — Include lists for known, typed block states
  • entities — Include lists for known, typed entities
  • block-entities — Include lists for known, typed block entities

§Other Features

  • docs — Enable this when building the docs
  • test — Enables all features required for running the tests

§Minecraft Version Features

  • mc-all — Enable all Minecraft version features
  • latest — Enable lists for the latest supported Minecraft version. Currently 1.20.5
  • 1.14 — Enable lists for Minecraft 1.14, extracted from Minecraft 1.14.4
  • 1.15 — Enable lists for Minecraft 1.15, extracted from Minecraft 1.15.1
  • 1.15.2 — Enable lists for Minecraft 1.15.2, extracted from Minecraft 1.15.2
  • 1.16 — Enable lists for Minecraft 1.16, extracted from Minecraft 1.16.1
  • 1.16.2 — Enable lists for Minecraft 1.16.2, extracted from Minecraft 1.16.5
  • 1.17 — Enable lists for Minecraft 1.17, extracted from Minecraft 1.17.1
  • 1.18 — Enable lists for Minecraft 1.18, extracted from Minecraft 1.18.2
  • 1.19 — Enable lists for Minecraft 1.19, extracted from Minecraft 1.19
  • 1.19.1 — Enable lists for Minecraft 1.19.1, extracted from Minecraft 1.19.2
  • 1.19.3 — Enable lists for Minecraft 1.19.3, extracted from Minecraft 1.19.3
  • 1.19.4 — Enable lists for Minecraft 1.19.4, extracted from Minecraft 1.19.4
  • 1.20 — Enable lists for Minecraft 1.20, extracted from Minecraft 1.20.1
  • 1.20.2 — Enable lists for Minecraft 1.20.2, extracted from Minecraft 1.20.2
  • 1.20.3 — Enable lists for Minecraft 1.20.3, extracted from Minecraft 1.20.4
  • 1.20.5 — Enable lists for Minecraft 1.20.5, extracted from Minecraft 1.20.6

Modules§

  • Defines data version constants for various Minecraft versions.
  • latestlatest
    Re-exports for all items of the latest Minecraft version.
  • mc1_141.14
    Types for Minecraft 1.14.
  • mc1_151.15
    Types for Minecraft 1.15.
  • mc1_15_21.15.2
    Types for Minecraft 1.15.2.
  • mc1_161.16
    Types for Minecraft 1.16.
  • mc1_16_21.16.2
    Types for Minecraft 1.16.2.
  • mc1_171.17
    Types for Minecraft 1.17.
  • mc1_181.18
    Types for Minecraft 1.18.
  • mc1_191.19
    Types for Minecraft 1.19.
  • mc1_19_11.19.1
    Types for Minecraft 1.19.1.
  • mc1_19_31.19.3
    Types for Minecraft 1.19.3.
  • mc1_19_41.19.4
    Types for Minecraft 1.19.4.
  • mc1_201.20
    Types for Minecraft 1.20.
  • mc1_20_21.20.2
    Types for Minecraft 1.20.2.
  • mc1_20_31.20.3
    Types for Minecraft 1.20.3.
  • mc1_20_51.20.5
    Types for Minecraft 1.20.5.
  • Other Minecraft related types.

Structs§

Traits§

  • Any type that can represent a block entity.
  • Any type that can represent a block state.
  • Any type that can represent an entity.